-
Notifications
You must be signed in to change notification settings - Fork 871
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove generated InstrumentationModule#getMuzzleReferences() method from the source code #4087
Conversation
…rom the source code
muzzle/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/MuzzleReferencesAccessor.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice
@@ -36,7 +37,14 @@ | |||
private final Set<String> helperClassNames; | |||
private final InstrumentationClassPredicate instrumentationClassPredicate; | |||
|
|||
public ReferenceMatcher( | |||
public static ReferenceMatcher of(InstrumentationModule instrumentationModule) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
muzzle/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/MuzzleReferencesAccessor.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice 👍
I think we can do the same thing for the new registerMuzzleContextStoreClasses()
method that I introduced recently.
*/ | ||
class MuzzleReferencesAccessor { | ||
private static final ClassValue<MethodHandle> getMuzzleReferences = | ||
new ClassValue<MethodHandle>() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that I think of it we don't really need to use ClassValue
s and MethodHandle
s - the getMuzzleReferences()
will be called exactly once per InstrumentationModule
implementation, so there's no need to cache the result here (it's already cached in the MuzzleMatcher
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure? Will be happy to remove this cache!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep -- the only place (MuzzleMatcher
) that constructs ReferenceMatcher
in the agent uses an AtomicBoolean initialized
field to make sure it only does it once (building a giant map of references can get expensive).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about io.opentelemetry.javaagent.tooling.muzzle.ClassLoaderMatcher#matchesAll
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I will try Lauri idea from #4087 (comment) anyway later on. That will probably remove this whole class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That one is only used in the gradle muzzle-check plugin, it doesn't affect the agent at all.
* generated automatically during compilation by the {@code | ||
* io.opentelemetry.instrumentation.javaagent-codegen} Gradle plugin. | ||
*/ | ||
class MuzzleReferencesAccessor { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps javaagent-codegen
should add an interface that has getMuzzleReferences
to instrumentation module so you wouldn't need to use reflection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume that MethodHandle has no performance overhead on invocation. But I will think about this idea, it may be more elegant indeed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will try this idea as a follow-up optimisation. I like it, but prefer to finish current iteration of removing ClassRef and friends from public API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will also be easier to extend with other muzzle-generated methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it is possible to build extension jars that contain instrumentation modules then all of the muzzle and codegen stuff has become part of our api. Have you thought about how to version it and how to handle cases where agent is incompatible with codegen version used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohhh, good question... The only vague thought I have atm is "javaagent must support all previous stable versions of codegen within any given major version." Which assumes "in sync" versioning of the agent and gradle plugins.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it is possible to build extension jars that contain instrumentation modules then all of the muzzle and codegen stuff has become part of our api
oh no, this is a great point, so maybe we shouldn't get rid of these classes from our public API? 😭
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These classes should be part of the contract between muzzle generation and muzzle verification. But no end-user, including extension authors, should see them.
It bothered me for a long time that we have a bunch of public classes in
io.opentelemetry.javaagent.extension.muzzle
package that in fact should never ever be used directly by the users ofjavaagent-extension-api
module. They are there and public only becauseInstrumentationModule#getMuzzleReferences()
exposes them. But that method is also should never be used by end-users. It is auto-generated and is used bymuzzle
andtooling
modules.This PR does the following:
InstrumentationModule#getMuzzleReferences()
method from the source codeMuzzleReferencesAccessor
class intomuzzle
module to access the generated version ofgetMuzzleReferences
method viaMethodHandle
getMuzzleReferences
method insideReferenceMatcher
class (andReferencesPrinter
)All of the above would allow us to move
io.opentelemetry.javaagent.extension.muzzle.ClassRef
class (and all related classes from that package) fromjavaagent-extension-api
module intomuzzle
, but unfortunately they are used bygradle-plugins
. So as preparation for the future, I created a verbatim copies of all classes fromio.opentelemetry.javaagent.extension.muzzle
package inio.opentelemetry.javaagent.tooling.muzzle.references
. Next PR can change gradle plugins to use these new classes. Old copies of them can be removed then fromjavaagent-extension-api
.